package com.moyq5.wifi.joystick;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.NetworkInfo;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.ActionListener;

import androidx.core.app.ActivityCompat;

import com.moyq5.wifi.joystick.worker.WorkerFacory;

import java.util.concurrent.Future;

import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.net.wifi.p2p.WifiP2pManager.BUSY;
import static android.net.wifi.p2p.WifiP2pManager.EXTRA_NETWORK_INFO;
import static android.net.wifi.p2p.WifiP2pManager.EXTRA_WIFI_P2P_DEVICE;
import static android.net.wifi.p2p.WifiP2pManager.EXTRA_WIFI_P2P_GROUP;
import static android.net.wifi.p2p.WifiP2pManager.EXTRA_WIFI_P2P_INFO;
import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION;
import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION;
import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION;
import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION;
import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION;

/**
 * wifi p2p 状态广播接收器
 */
public class WifiP2pClientReceiver extends BroadcastReceiver {
    private static final Console console = ConsoleFactory.get(WifiP2pClientReceiver.class);

    private final WifiP2pManager mManager;
    private final WifiP2pManager.Channel mChannel;
    private final Activity mActivity;

    private static Future<?> discoverFuture;

    public WifiP2pClientReceiver(WifiP2pManager manager, WifiP2pManager.Channel channel,
                                 Activity activity) {
        super();
        this.mManager = manager;
        this.mChannel = channel;
        this.mActivity = activity;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        console.info("P2P action: %s", action);
        if (ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            console.warn("权限不足：%s", ACCESS_FINE_LOCATION);
            return;
        }
        if (WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) {
            int state = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, -1);
            if (state == WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED) {
                discoverPeers();
                return;
            }
            if (null != discoverFuture && !discoverFuture.isDone()) {
                discoverFuture.cancel(true);
            }
        } else if (WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
            int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
            if (state != WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
                console.warn("P2P 不可用: %d", state);
                return;
            }
        } else if (WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
            mManager.requestPeers(mChannel, peers -> {
                console.info("P2P 设备列表：%s", peers.getDeviceList().toString());
                peers.getDeviceList().forEach(device -> {
                    connect(context, device);
                });
            });
        } else if (WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
            WifiP2pInfo p2pInfo = intent.getParcelableExtra(EXTRA_WIFI_P2P_INFO);
            NetworkInfo networkInfo = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
            WifiP2pGroup group = intent.getParcelableExtra(EXTRA_WIFI_P2P_GROUP);
            console.info("P2P p2pInfo：%s", p2pInfo.toString());
            console.info("P2P networkInfo：%s", networkInfo.toString());
            console.info("P2P group：%s", group.toString());
            if (p2pInfo.groupFormed && null != p2pInfo.groupOwnerAddress) {
                ThreadKit.execute(() -> {
                    console.info("P2P hostName：%s", p2pInfo.groupOwnerAddress.getHostAddress());
                    WorkerFacory.enqueveNettyClientOneTime(context, p2pInfo.groupOwnerAddress.getHostAddress(), 8080);
                });
            } else if (!networkInfo.isConnected()) {
                discoverPeers();
            }
        } else if (WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
            // Respond to this device's wifi state changing
            WifiP2pDevice device = intent.getParcelableExtra(EXTRA_WIFI_P2P_DEVICE);
            console.info("P2P device：%s", device.toString());
            connect(context, device);
        }

    }

    @SuppressLint("MissingPermission")
    private void discoverPeers() {
        console.debug("P2P 启动发现...");
        mManager.discoverPeers(mChannel, new ActionListener() {
            @Override
            public void onSuccess() {
                console.info("P2P 启动发现，成功");
            }

            @Override
            public void onFailure(int reason) {
                console.info("P2P 启动发现，失败：%s", reason);
                if (null != discoverFuture && !discoverFuture.isDone()) {
                    discoverFuture.cancel(true);
                }
                if (BUSY == reason) {
                    return;
                }
                discoverFuture = ThreadKit.submit(() -> {
                    try {
                        Thread.sleep(10000);
                        discoverPeers();
                    } catch (InterruptedException ignored) {

                    }
                });
            }
        });
    }

    @SuppressLint("MissingPermission")
    private void connect(Context context, WifiP2pDevice device) {
        if (WifiP2pDevice.CONNECTED == device.status) {
            //console.info("P2P 已连接：%s on %s", peer.deviceName, peer.deviceAddress);
            return;
        }
        if (WifiP2pDevice.AVAILABLE != device.status) {
            //console.info("P2P 不可用：%s on %s is %d", peer.deviceName, peer.deviceAddress, peer.status);
            return;
        }
        console.info("P2P 开始连接：%s on %s", device.deviceName, device.deviceAddress);
        WifiP2pConfig config = new WifiP2pConfig();
        config.deviceAddress = device.deviceAddress;
        //config.wps
        mManager.connect(mChannel, config, new ActionListener() {
            @Override
            public void onSuccess() {
                console.info("P2P 连接成功：%s on %s", device.deviceName, device.deviceAddress);
                mManager.requestConnectionInfo(mChannel, info -> {
                    console.info("P2P p2pInfo：%s", info);
                    if (info.groupFormed && null != info.groupOwnerAddress) {
                        ThreadKit.execute(() -> {
                            WorkerFacory.enqueveNettyClientOneTime(context, info.groupOwnerAddress.getHostAddress(), 9999);
                        });
                    }
                });
            }

            @Override
            public void onFailure(int reason) {
                console.error("P2P 连接失败：%s on %s reason: %d", device.deviceName, device.deviceAddress, reason);
            }
        });
    }
}
